package com.codefish.framework.spring.context.event;

import com.codefish.framework.spring.context.ApplicationEvent;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/10/10 下午 03:26
 */
public class AbstractApplicationEventMulticaster implements IApplicationEventMulticaster {

    private final Set<IApplicationListener<?>> applicationListenerList = new HashSet<>();

    @Override
    public void addApplicationListener(IApplicationListener<?> applicationListener) {
        applicationListenerList.add(applicationListener);
    }

    @Override
    public void removeApplicationListener(IApplicationListener<?> applicationListener) {
        applicationListenerList.remove(applicationListener);
    }

    @Override
    public void multicastEvent(ApplicationEvent applicationEvent) {
        for (IApplicationListener<?> listener : applicationListenerList) {
            executeEvent(listener, applicationEvent);
        }
    }

    protected void executeEvent(IApplicationListener<?> listener, ApplicationEvent event) {
        Method[] methods = listener.getClass().getMethods();
        Class<?>[] types;
        for (Method method : methods) {
            if ("onApplicationEvent".equals(method.getName()) && (types = method.getParameterTypes()).length == 1) {
                Class<?> tarEventType = types[0];
                if (tarEventType.isAssignableFrom(event.getClass())) {
                    try {
                        method.invoke(listener, event);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        //ignore
                    }
                    break;
                }
            }
        }
    }
}
